﻿using System;
using System.Collections.Generic;
using MugenInjection.Interface.Components;

namespace MugenInjection.Interface
{
    /// <summary>
    /// An internal container that manages and resolves components.
    /// </summary>
    public interface IComponentContainer : IEnumerable<IComponent>, IDisposableObject
    {
        /// <summary>
        /// Gets the number of elements contained in the <see cref="IBindingCollection"/>.
        /// </summary>
        /// <returns>
        /// The number of elements contained in the <see cref="IBindingCollection"/>.
        /// </returns>
        int Count { get; }

        /// <summary>
        /// Indicates that the component will be disposed after unload (Default is <value>true</value>).
        /// </summary>
        bool DisposeComponentAfterUnload { get; set; }

        /// <summary>
        /// Gets or sets the specified <see cref="IBindingManagerComponent"/> for manage bindings.
        /// </summary>
        IBindingManagerComponent BindingManagerComponent { get; set; }

        /// <summary>
        /// Gets or sets the specified <see cref="IBindingActivatorComponent"/> for activate binding.
        /// </summary>
        IBindingActivatorComponent BindingActivatorComponent { get; set; }

        /// <summary>
        /// Binds a collection to the <see cref="IInjector"/>.
        /// </summary>
        /// <param name="injector">The specified <see cref="IInjector"/>.</param>
        void Initialize(IInjector injector);

        /// <summary>
        /// Adds the specified <see cref="IComponent"/>.
        /// </summary>
        /// <param name="component">The specified <see cref="IComponent"/>.</param>
        void Add(IComponent component);

        /// <summary>
        /// Removes the specified <see cref="IComponent"/>.
        /// </summary>
        /// <param name="component">The specified <see cref="IComponent"/>.</param>
        bool Remove(IComponent component);

        /// <summary>
        /// Removes all components with the specified <see cref="Type"/>.
        /// </summary>
        /// <typeparam name="T">The specified <see cref="Type"/>.</typeparam>
        void RemoveAll<T>() where T : IComponent;

        /// <summary>
        /// Gets the component with the specified <see cref="Type"/>.
        /// </summary>
        /// <typeparam name="T">The specified <see cref="Type"/>.</typeparam>
        /// <returns>An instance of <see cref="IComponent"/>.</returns>
        T Get<T>() where T : IComponent;

        /// <summary>
        /// Tries get the component with the specified <see cref="Type"/>.
        /// </summary>
        /// <typeparam name="T">The specified <see cref="Type"/>.</typeparam>
        /// <param name="component">An instance of <see cref="IComponent"/>.</param>
        /// <returns><c>True</c> if the component finds; otherwise, <c>false</c>.</returns>
        bool TryGet<T>(out T component) where T : IComponent;

        /// <summary>
        /// Indicates that the specified <see cref="Type"/> of component exists in the collection.
        /// </summary>
        /// <typeparam name="T">The specified component <see cref="Type"/>.</typeparam>
        /// <returns><c>True</c> if the specified component exist; otherwise, <c>false</c>.</returns>
        bool IsExist<T>();

        /// <summary>
        /// Indicates that the specified <see cref="Type"/> of component exists in the collection.
        /// </summary>
        /// <param name="componentType">The specified component <see cref="Type"/>.</param>
        /// <returns><c>True</c> if the specified component exist; otherwise, <c>false</c>.</returns>
        bool IsExist(Type componentType);

        /// <summary>
        /// Indicates that the <see cref="IComponent"/> component exists in the collection.
        /// </summary>
        /// <param name="component">The specified component <see cref="IComponent"/>.</param>
        /// <returns><c>True</c> if the specified component exist; otherwise, <c>false</c>.</returns>
        bool IsContain(IComponent component);

        /// <summary>
        /// Gets all components with the specified <see cref="Type"/>.
        /// </summary>
        /// <typeparam name="T">The specified <see cref="Type"/>.</typeparam>
        /// <returns>An instances of <see cref="IComponent"/>.</returns>
        IList<IComponent> GetAll<T>() where T : IComponent;

        /// <summary>
        /// Creates a new object that is a copy of the current components.
        /// </summary>
        /// <returns>A new object that is a copy of this instance.</returns>
        IList<IComponent> CloneAll();

        /// <summary>
        /// Occurs after add specified <see cref="IComponent"/>.
        /// </summary>
        event Action<IComponent> AddedComponent;

        /// <summary>
        /// Occurs after remove specified <see cref="IComponent"/>.
        /// </summary>
        event Action<IComponent> RemovedComponent;
    }
}